package forestsimulatorp3.model.position;

import java.util.HashSet;
import java.util.Set;
import model.enums.Movement;

/**
 * Controls the rules of movement on the forest.
 * @author dielson
 *
 */
public class Area {

    // Attributes
    private final int MIN_X = 0;
    private final int MIN_Y = 0;
    // The max value of x
    private final int MAX_X;
    // The max value of y
    private final int MAX_Y;
    private Set<Square> occupiedPositions;

    // Constructors ------------------------------------------------------------
    /**
     * Creates and Area of dimensions x and y
     * @param x the horizontal size
     * @param y the vertical size
     */
    public Area(int x, int y) {
        this.MAX_X = x - 1;
        this.MAX_Y = y - 1;
        occupiedPositions = new HashSet<Square>();
    }

    // Public methods ----------------------------------------------------------
    public Set<Square> getOccupiedPositions() {
        return occupiedPositions;
    }

    public void setOccupiedPositions(Set<Square> positions) {
        this.occupiedPositions = positions;
    }

    public boolean addOccupiedPosition(Square position) {
        return occupiedPositions.add(position);
    }
    
    public boolean removePosition(Square position) {
        return occupiedPositions.remove(position);
    }

    public Square getSquareInstance(int x, int y) {

        for (Square sq : occupiedPositions) {
            if (sq.getX() == x && sq.getY() == y) {
                return sq;
            }
        }
        Square newSquare = new Square(x, y);
        occupiedPositions.add(newSquare);
        return newSquare;
    }

    /**
     * Returns the position that the animal will turn when moving to any direction
     * @param from
     * @param movement
     * @return the final position
     */
    public Square getNext(Square from, Movement movement) {
        if (movement == Movement.UP) {
            return getUpMovement(from);
        } else if (movement == Movement.DOWN) {
            return getDownMovement(from);
        } else if (movement == Movement.RIGHT) {
            return getRightMovement(from);
        } else {
            return getLeftMovement(from);
        }
    }

    /**
     * Returns all the surrounding positions, starting from the upward and going
     * on the clockwise direction.
     * @param from
     * @param manager
     * @return
     */
    public Square[] getSurroudingPositions(Square from) {
        Square[] surroudings = new Square[4];
        surroudings[0] = getNext(from, Movement.UP);
        surroudings[1] = getNext(from, Movement.RIGHT);
        surroudings[2] = getNext(from, Movement.DOWN);
        surroudings[3] = getNext(from, Movement.LEFT);
        return surroudings;
    }

    // Private methods ---------------------------------------------------------

    private Square getUpMovement(Square from) {
        if (from.getY() == MIN_Y) {
            return from;
        }
        return getSquareInstance(from.getX(), from.getY() - 1);
    }

    private Square getDownMovement(Square from) {
        if (from.getY() == MAX_Y) {
            return from;
        }
        return getSquareInstance(from.getX(), from.getY() + 1);
    }

    private Square getLeftMovement(Square from) {
        if (from.getX() == MIN_X) {
            return from;
        }
        return getSquareInstance(from.getX() - 1, from.getY());
    }

    private Square getRightMovement(Square from) {
        if (from.getX() == MAX_X) {
            return from;
        }
        return getSquareInstance(from.getX() + 1, from.getY());
    }

    // Getters & setters -------------------------------------------------------

    public int getMinX() {
        return MIN_X;
    }
    
    public int getMaxX() {
        return MAX_X;
    }
    
    public int getMinY() {
        return MIN_Y;
    }

    public int getMaxY() {
        return MAX_Y;
    }
}
